package rabbitMq

import (
	"github.com/streadway/amqp"
	"log"
	"project/config"
	"project/tool/logs"
	"sync"
)

//定义rabbitMq对象
type RabbitMQ struct {
	Connect			*amqp.Connection
	Channel 		*amqp.Channel
	QueueName		string	//队列名称
	ExchangeName	string	//交换机名称
	BindKey			string	//绑定得key名称
	Addr 			string	//rabbit连接地址
	Mu				sync.Mutex
}

func outErr(err error, msg string)  {
	if err != nil {
		log.Fatalf("%s:%s", msg, err)
	}
}

//new rabbitMq 结构体
func NewRabbitMQ(queueName,exchangeName,bindKey,addr string) *RabbitMQ {
	return &RabbitMQ{
		QueueName:    queueName,
		ExchangeName: exchangeName,
		BindKey:      bindKey,
		Addr:         addr,
	}
}

//初始化RabbitMQ 客户端连接
func NewRabbitMQSimple(queueName,addr string) *RabbitMQ {
	rabbitMq := NewRabbitMQ(queueName,"","",addr)
	var err error
	rabbitMq.Connect, err = amqp.Dial(rabbitMq.Addr)
	outErr(err,"fail to connect rabbitMq")
	rabbitMq.Channel, err = rabbitMq.Connect.Channel()
	outErr(err,"fail to open channel")
	return rabbitMq
}

//断开channel 和 connection
func (r *RabbitMQ) Destory() {
	r.Channel.Close()
	r.Connect.Close()
}

//发布及时队列
func (r *RabbitMQ) PublishSimple(message string) error {
	r.Mu.Lock()
	defer r.Mu.Unlock()

	//将消息发送至消费队列
	err := r.Channel.Publish(
		"",	//交换机，可留空
		config.RabbitMqConf.QueueName,		//队列名称
		false,
		false,
		amqp.Publishing{
			ContentType: "text/plain",
			Body:        []byte(message),
		})

	if err != nil {
		logs.Errorf("发布直接模式队列有误,err:%s", err)
		return err
	}
	return nil
}

//发布延迟队列
func (r *RabbitMQ) PublishDelay(message string, delayTime string) error {
	r.Mu.Lock()
	defer r.Mu.Unlock()

	//声明一个延时队列，并设置交换机
	q, err := r.Channel.QueueDeclare(
			config.RabbitMqConf.DelayQueueName,		//延迟队列名称
			true,							//是否持久化
			false,						//是否自动删除
			false,							//如果设置为排他，则队列仅对首次声明他的连接可见，并在连接断开时自动删除
			false,							//是否非阻塞
			amqp.Table{
				"x-dead-letter-exchange": "delayExchange",		//延迟交换机
			})

	//发布消息至延迟队列
	err = r.Channel.Publish(
		"",
		q.Name,
		false,
		false,
		amqp.Publishing{
			ContentType:     "text/plain",		// 设置过期时间
			Expiration:     delayTime,
			Body:           []byte(message),
		})
	if err != nil {
		logs.Errorf("发布延迟队列有误,err:%s", err)
		return err
	}
	return nil
}
